/*
 * BSM6.0
 *
 * Copyright 2012-2013 (C) SINODATA CO., LTD. All Rights Reserved.
 */
package com.sinodata.bsm.cicp.service;

import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Vector;

import org.apache.log4j.Logger;
import org.snmp4j.CommandResponder;
import org.snmp4j.CommandResponderEvent;
import org.snmp4j.MessageDispatcherImpl;
import org.snmp4j.PDU;
import org.snmp4j.PDUv1;
import org.snmp4j.Snmp;
import org.snmp4j.TransportMapping;
import org.snmp4j.mp.MPv1;
import org.snmp4j.mp.MPv2c;
import org.snmp4j.mp.MPv3;
import org.snmp4j.security.SecurityModels;
import org.snmp4j.security.SecurityProtocols;
import org.snmp4j.security.USM;
import org.snmp4j.smi.Address;
import org.snmp4j.smi.GenericAddress;
import org.snmp4j.smi.OctetString;
import org.snmp4j.smi.TcpAddress;
import org.snmp4j.smi.UdpAddress;
import org.snmp4j.smi.VariableBinding;
import org.snmp4j.transport.DefaultTcpTransportMapping;
import org.snmp4j.transport.DefaultUdpTransportMapping;
import org.snmp4j.util.MultiThreadedMessageDispatcher;
import org.snmp4j.util.ThreadPool;

import com.sinodata.bsm.cicp.message.Messenger;
import com.sinodata.bsm.cicp.util.SystemContext;
import com.sinodata.bsm.common.vo.FaultTrapMsg;

/**
 * <p>
 * Description: 
 * </p>
 *
 * @author wangyazhou
 * @version 1.0

 * <p>
 * History: 
 *
 * Date                     Author         Version     Description
 * ---------------------------------------------------------------------------------
 * 2012-12-10 上午11:45:08          wangyazhou        1.0         To create
 * </p>
 *
 * @since 
 * @see     
 */
public class TrapReceiverDeamon implements CommandResponder {

    private static final Logger logger = Logger.getLogger("traplog");

    private static final SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

    //trap服务的状态
    public static String TRAP_SERVICE_STATUS = "NO";

    /**
     * 初始化TRAP的监听服务
     */
    public void init() {
        try {

            String open = (String) SystemContext.getProperty("trap.open", "false");
            if ("false".equals(open)) {
                return;
            }

            ThreadPool threadPool = ThreadPool.create("Trap", 10);
            MultiThreadedMessageDispatcher dispatcher = new MultiThreadedMessageDispatcher(threadPool, new MessageDispatcherImpl());
            Address listenAddress = GenericAddress.parse((String) SystemContext.getProperty("trap.adress", "udp:localhost/162")); // 本地IP与监听端口  udp:10.0.66.76/162
            TransportMapping transport;
            // 对TCP与UDP协议进行处理 
            if (listenAddress instanceof UdpAddress) {
                transport = new DefaultUdpTransportMapping((UdpAddress) listenAddress);
            } else {
                transport = new DefaultTcpTransportMapping((TcpAddress) listenAddress);
            }
            Snmp snmp = new Snmp(dispatcher, transport);
            snmp.getMessageDispatcher().addMessageProcessingModel(new MPv1());
            snmp.getMessageDispatcher().addMessageProcessingModel(new MPv2c());
            snmp.getMessageDispatcher().addMessageProcessingModel(new MPv3());
            USM usm = new USM(SecurityProtocols.getInstance(), new OctetString(MPv3.createLocalEngineID()), 0);
            SecurityModels.getInstance().addSecurityModel(usm);
            snmp.addCommandResponder(this);
            snmp.listen();
            TRAP_SERVICE_STATUS = (String) SystemContext.getProperty("trap.adress");
            logger.info("[TIP]\tStart Trap Listening Deamon..");
        } catch (Exception e) {
            logger.error(e);
        }
    }

    @SuppressWarnings("unchecked")
    @Override
    public void processPdu(CommandResponderEvent respEvnt) {
        logger.info("\n\n[Receive A Trap At]\t" + sf.format(Calendar.getInstance().getTime()));
        logger.info("peeradress=" + respEvnt.getPeerAddress().toString());
        logger.info("level=" + respEvnt.getSecurityLevel());
        logger.info("medel=" + respEvnt.getSecurityModel());
        logger.info("name=" + new OctetString(respEvnt.getSecurityName()));
        logger.info("PDU=" + respEvnt.getPDU().toString());

        FaultTrapMsg trap = new FaultTrapMsg();
        try {
            String adress = respEvnt.getPeerAddress().toString();
            trap.setIp(adress.split("[/]")[0]);
            trap.setRecevTime(Calendar.getInstance().getTime());
            trap.setSecLevel(respEvnt.getSecurityLevel());
            trap.setSecName(new OctetString(respEvnt.getSecurityName()).toString());
            int model = respEvnt.getSecurityModel();
            if (1 == model) {
                PDUv1 pduv1 = (PDUv1) respEvnt.getPDU();
                logger.info("pdutype=" + pduv1.getType());
                trap.setEnterprise(pduv1.getEnterprise().toString());
                trap.setRequestId(pduv1.getRequestID().toLong());
                trap.setErrorStatus(pduv1.getErrorStatus() + "");
                trap.setErrorIndex(pduv1.getErrorIndex() + "");
                trap.setGenericTrap(pduv1.getGenericTrap() + "");
                trap.setSpecificTrap(pduv1.getSpecificTrap() + "");
                trap.setTimeStamp(pduv1.getTimestamp() + "");
                trap.setVersion("1");
                String[] stry = new String[10];
                Vector<VariableBinding> recVBs = pduv1.getVariableBindings();
                // trap.setMsg(recVBs.toString());
                StringBuilder sb = new StringBuilder("VBS[");
                if (recVBs != null) {
                    for (int i = 0; i < Math.min(recVBs.size(), 10); i++) {
                        VariableBinding recVB = recVBs.elementAt(i);
                        logger.info(recVB.getOid() + " : " + recVB.getVariable());
                        sb.append(recVB.getOid() + "=");
                        sb.append(recVB.getVariable() == null ? "" : recVB.getVariable().toString().trim());
                        sb.append(" ;");
                        stry[i] = recVB.getVariable().toString();
                    }
                }
                sb.append("]");
                String msg = sb.toString();
                trap.setMsg(msg.length() > 2048 ? msg.substring(0, 2048) : msg);
                trap.setMsg1(stry[0] == null ? "" : stry[0].trim());
                trap.setMsg2(stry[1] == null ? "" : stry[1].trim());
                trap.setMsg3(stry[2] == null ? "" : stry[2].trim());
                trap.setMsg4(stry[3] == null ? "" : stry[3].trim());
                trap.setMsg5(stry[4] == null ? "" : stry[4].trim());
                trap.setMsg6(stry[5] == null ? "" : stry[5].trim());
                trap.setMsg7(stry[6] == null ? "" : stry[6].trim());
                trap.setMsg8(stry[7] == null ? "" : stry[7].trim());
                trap.setMsg9(stry[8] == null ? "" : stry[8].trim());
                trap.setMsg10(stry[9] == null ? "" : stry[9].trim());
            } else {
                if (2 == model) {
                    trap.setVersion("2");
                } else if (3 == model) {
                    trap.setVersion("3");
                }
                PDU pduv2 = respEvnt.getPDU();
                logger.info("pduv2=" + pduv2.getType());
                trap.setRequestId(pduv2.getRequestID().toLong());
                trap.setErrorStatus(pduv2.getErrorStatus() + "");
                trap.setErrorIndex(pduv2.getErrorIndex() + "");
                trap.setGenericTrap("");
                trap.setSpecificTrap("");
                String[] stry = new String[12];
                Vector<VariableBinding> recVBs = pduv2.getVariableBindings();
                //                trap.setMsg(recVBs.toString());
                StringBuilder sb = new StringBuilder("VBS[");
                if (recVBs != null) {
                    for (int i = 0; i < Math.min(recVBs.size(), 12); i++) {
                        VariableBinding recVB = recVBs.elementAt(i);
                        logger.info(recVB.getOid() + " : " + recVB.getVariable());
                        sb.append(recVB.getOid() + "=");
                        sb.append(recVB.getVariable() == null ? "" : recVB.getVariable().toString().trim());
                        sb.append(" ;");
                        stry[i] = recVB.getVariable().toString();
                    }
                }
                sb.append("]");
                String msg = sb.toString();
                trap.setMsg(msg.length() > 2048 ? msg.substring(0, 2048) : msg);
                trap.setTimeStamp(stry[0] == null ? "" : stry[0].trim());
                trap.setExtMsg(stry[1] == null ? "" : stry[1].trim());
                trap.setMsg1(stry[2] == null ? "" : stry[2].trim());
                trap.setMsg2(stry[3] == null ? "" : stry[3].trim());
                trap.setMsg3(stry[4] == null ? "" : stry[4].trim());
                trap.setMsg4(stry[5] == null ? "" : stry[5].trim());
                trap.setMsg5(stry[6] == null ? "" : stry[6].trim());
                trap.setMsg6(stry[7] == null ? "" : stry[7].trim());
                trap.setMsg7(stry[8] == null ? "" : stry[8].trim());
                trap.setMsg8(stry[9] == null ? "" : stry[9].trim());
                trap.setMsg9(stry[10] == null ? "" : stry[10].trim());
                trap.setMsg10(stry[11] == null ? "" : stry[11].trim());
            }
            Messenger.getInstance().sendTrap(trap);
        } catch (Exception e) {
            logger.error(e);
        }
    }
}
